home *** CD-ROM | disk | FTP | other *** search
- ;;; -*- Scheme -*-
-
- #|
- Description:
-
- Heap sort using fixnums as vector indeces.
-
- Usage:
-
- (sort '(10 9 8 7 6 5 4 3 2 1) <) -> (1 2 3 4 5 6 7 8 9 10)
- (sort '#(10 9 8 7 6 5 4 3 2 1) <) -> #(1 2 3 4 5 6 7 8 9 10)
- (define foo '#(10 9 8 7 6 5 4 3 2 1))
- (sort! foo <)
- foo -> #(1 2 3 4 5 6 7 8 9 10)
-
- |#
-
- (declare (usual-integrations 1+ -1+ + = < > integer-divide)
- (integrate-primitive-procedures
- (-1+ minus-one-plus-fixnum)
- (1+ one-plus-fixnum)
- (+ plus-fixnum)
- (= equal-fixnum?)
- (< less-than-fixnum?)
- (> greater-than-fixnum?)
- (integer-divide divide-fixnum)))
-
- (let-syntax ((define-integrable
- (macro (params . body)
- `(begin
- (declare (integrate-operator ,(car params)))
- (define ,(car params)
- (named-lambda ,params
- (declare (integrate ,@(cdr params)))
- ,@body))))))
-
- (define (sort obj pred)
- (cond ((pair? obj)
- (vector->list (sort! (list->vector obj) pred)))
- ((vector? obj)
- (sort! (vector-copy obj) pred))
- ((null? obj)
- '())
- (else
- (error "sort: argument should be a list or a vector"))))
-
- (define (sort! vec pred)
- (define-integrable (quo x y)
- (car (integer-divide x y)))
-
- (define-integrable (exchange! i j)
- (let ((old (vector-ref vec i)))
- (vector-set! vec i (vector-ref vec j))
- (vector-set! vec j old)))
-
- (define (heapify-up n)
- (let ((next (quo (-1+ n) 2)))
- (if (and (not (zero? n))
- (not (pred (vector-ref vec n)
- (vector-ref vec next))))
- (begin
- (exchange! n next)
- (heapify-up next)))))
-
- (define (heapify-down n max)
- (define-integrable (check m)
- (if (pred (vector-ref vec n)
- (vector-ref vec m))
- (begin
- (exchange! n m)
- (heapify-down m max))))
-
- (let* ((p (+ n (1+ n)))
- (q (1+ p)))
- (if (and (not (> q max))
- (not (pred (vector-ref vec q)
- (vector-ref vec p))))
- (check q)
- (if (not (> p max))
- (check p)))))
-
- (if (not (vector? vec))
- (error "sort!: argument must be a vector" vec))
-
- (let ((max (-1+ (vector-length vec))))
-
- (define (heapify-loop n)
- (if (not (> n max))
- (begin
- (heapify-up n)
- (heapify-loop (1+ n)))))
-
- (define (sort-loop dest)
- (if (> dest 0)
- (begin
- (exchange! dest 0)
- (heapify-down 0 (-1+ dest))
- (sort-loop (-1+ dest)))))
-
- (heapify-loop 0)
- (sort-loop max)
- vec))
- ) ;; End of let-syntax